import * as WebSocket from 'ws';
import {
  WebSocketAdapter,
  INestApplicationContext,
  Injectable,
} from '@nestjs/common';
import { MessageMappingProperties } from '@nestjs/websockets';
import { param2Obj } from 'src/share';
import { JwtService } from '@nestjs/jwt';
import { jwtSecret } from 'src/constants';
import wsMap from './ws.container';

@Injectable()
export class WsAdapter implements WebSocketAdapter {
  jwtService: JwtService;
  constructor(private app: INestApplicationContext) {
    this.jwtService = new JwtService({
      secret: jwtSecret,
    });
  }

  create(port: number, options: any = {}): any {
    return new WebSocket.Server({ port, ...options });
  }

  bindClientConnect(server, callback: Function) {
    server.on('connection', async (e: WebSocket, req: { url: any }) => {
      try {
        const obj = param2Obj(req.url);
        const result = await this.jwtService.verify(obj['token']);
        const id = result.sub;
        if (typeof id === 'string') {
          // 将id存入对应的client
          e['__id__'] = id;
          wsMap.set(id, e);
        }
        callback(e, req);
      } catch (err) {
        console.error(err);
        e.close();
      }
    });
  }

  bindMessageHandlers(client: WebSocket, handlers: MessageMappingProperties[]) {
    client.addEventListener('message', async (e) => {
      try {
        const data = JSON.parse(e.data.toString());
        const symbol_id = data.symbol_id;
        const handler = handlers.find((i) => i.message === data.event);
        console.log(data);
        if (handler) {
          const res = await handler.callback(data.data);
          if (res) {
            client.send(
              JSON.stringify({
                ...res,
                symbol_id,
              }),
            );
          }
        }
      } catch (err) {}
    });
    client.addEventListener('close', (e) => {
      const id = client['__id__'];
      // 检测到关闭后，将该client从在线名单中移除
      wsMap.delete(id);
    });
  }

  close(server) {
    server.close();
  }
}
